package org.nbict.iot.persist.repo;

import org.nbict.iot.PropertyUtil;
import org.nbict.iot.persist.Repo;
import org.nbict.iot.task.once.Pointer;
import redis.clients.jedis.Jedis;
import redis.clients.jedis.JedisPool;
import redis.clients.jedis.JedisPoolConfig;
import redis.clients.jedis.Pipeline;

import java.time.Duration;
import java.util.List;
import java.util.Set;

/**
 * Created by songseven on 18/7/12.
 */
public class RedisRepo implements Repo {

    public RedisRepo() {
        init();
    }
    private JedisPool jedisPool;

    private void init() {
        final JedisPoolConfig poolConfig = buildPoolConfig();
        String url = PropertyUtil.getProperty("redis.url");
        String password = PropertyUtil.getProperty("redis.password");
        if (password != null) {
            jedisPool = new JedisPool(poolConfig, url, 6379, 2000, password, 0);//0数据库
        } else {
            jedisPool = new JedisPool(poolConfig, url);
        }
    }

    private JedisPoolConfig buildPoolConfig() {

        final JedisPoolConfig poolConfig = new JedisPoolConfig();
        poolConfig.setMaxTotal(128);
        poolConfig.setMaxIdle(128);
        poolConfig.setMinIdle(16);
        poolConfig.setTestOnBorrow(true);
        poolConfig.setTestOnReturn(true);
        poolConfig.setTestWhileIdle(true);
        poolConfig.setMinEvictableIdleTimeMillis(Duration.ofSeconds(60).toMillis());
        poolConfig.setTimeBetweenEvictionRunsMillis(Duration.ofSeconds(30).toMillis());
        poolConfig.setNumTestsPerEvictionRun(3);
        poolConfig.setBlockWhenExhausted(true);
        return poolConfig;
    }

    public void putZSet(List<Pointer> pointers) {
        try (Jedis jedis = jedisPool.getResource()) {
            Pipeline pipeline = jedis.pipelined(); //利用管道批量操作
            pointers.forEach(p-> {
                pipeline.zadd(p.vin(), p.currentTime(), p.toJSONString());
            });
            pipeline.sync();
        }
    }

    public Set<String> getZSet(String key, Long from, Long to) {
        //System.out.println(key + " => from: " + from + " to: " + to);
        Set<String> sets = null;
        try (Jedis jedis = jedisPool.getResource()) {
            sets = jedis.zrange(key, from, to);
        } catch (Exception e) {
            //log
        }
        return sets;
    }

    public Long getSize(String key) {
        Long size = 0l;
        try (Jedis jedis = jedisPool.getResource()) {
            size = jedis.zcard(key);
        }
        return size;
    }

    public Set<String> getKeys(String pattern) {

        Set<String> keys;
        try (Jedis jedis = jedisPool.getResource()) {
            keys = jedis.keys(pattern);
        }
        return keys;
    }

    public void removeWithin(String key, long from, long to) {
        try (Jedis jedis = jedisPool.getResource()) {
            jedis.zremrangeByScore(key, String.valueOf(from + 1), String
                    .valueOf(to - 1));
        } catch (Exception e) {
            e.printStackTrace();
        }
    }

    public void removeWith(String key, long from, long to) {
        try (Jedis jedis = jedisPool.getResource()) {
            jedis.zremrangeByScore(key, String.valueOf(from), String
                    .valueOf(to));
        } catch (Exception e) {
            e.printStackTrace();
        }
    }

//    public void removeLeft(String key, long from, long to) {
//        try (Jedis jedis = jedisPool.getResource()) {
//            jedis.zremrangeByScore(key, String.valueOf(from), String
//                    .valueOf(to - 1));
//        } catch (Exception e) {
//            e.printStackTrace();
//        }
//    }
}
